package org.jsola.hr.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.jsola.common.BeanKit;
import org.jsola.common.CollectionKit;
import org.jsola.common.DateKit8;
import org.jsola.common.StrKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ContractFieldToString;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.common.task.TaskKit;
import org.jsola.hr.constant.ContractDateEnum;
import org.jsola.hr.constant.ContractStatusEnum;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpPaperContractDAO;
import org.jsola.hr.dto.*;
import org.jsola.hr.entity.CompanyDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.entity.EmpPaperContractDO;
import org.jsola.hr.provider.IFileProviderService;
import org.jsola.hr.provider.INoticeProviderService;
import org.jsola.hr.query.EmpInfoExportColumn;
import org.jsola.hr.query.EmpPaperContractQuery;
import org.jsola.hr.service.ICompanyService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.service.IEmpPaperContractService;
import org.jsola.hr.service.excel.EmpPaperContractListener;
import org.jsola.hr.task.SendNoticeTask;
import org.jsola.hr.vo.*;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.notice.vo.NoticeRuleSettingVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.core.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.util.HtmlUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 纸质合同
 *
 * @author zhr
 */
@Service("hrEmpPaperContractServiceImpl")
@Slf4j
public class EmpPaperContractServiceImpl implements IEmpPaperContractService {

    @Autowired
    private IEmpPaperContractDAO empPaperContractDAO;

    @Autowired
    private INoticeProviderService noticeProviderService;

    @Autowired
    private SendNoticeTask sendNoticeTask;

    @Autowired
    private TaskKit taskKit;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private ICompanyService companyService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpPaperContractVO save(EmpPaperContractAddDTO empPaperContractAddDTO, TokenUser tokenUser) {
        if (StringUtil.isBlank(empPaperContractAddDTO.getName())) {
            empPaperContractAddDTO.setName("未命名合同");
        }
        // 根据合同开始时间和结束时间 设置合同状态
        Integer contractStatus = getStatus(empPaperContractAddDTO.getStartTime(), empPaperContractAddDTO.getEndTime());
        empPaperContractAddDTO.setStatus(contractStatus);
        // 转DO
        EmpPaperContractDO empPaperContractDO = empPaperContractAddDTO.to(EmpPaperContractDO.class);
        // 保存
        empPaperContractDO = save(empPaperContractDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empPaperContractDO.to(EmpPaperContractVO.class);
    }


    @Override
    public Integer onlySave(EmpPaperContractDO empPaperContractDO) {

        if (StringUtil.isBlank(empPaperContractDO.getName())) {
            empPaperContractDO.setName("未命名合同");
        }
        return empPaperContractDAO.insert(empPaperContractDO);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpPaperContractUpdateDTO empPaperContractUpdateDTO, TokenUser tokenUser) {
        EmpPaperContractDO empPaperContractDO = selectDOById(empPaperContractUpdateDTO.getId(), tokenUser.getSiteId());

        // 根据合同开始时间和结束时间 设置合同状态
        Integer contractStatus = getStatus(empPaperContractUpdateDTO.getStartTime(), empPaperContractUpdateDTO.getEndTime());
        empPaperContractUpdateDTO.setStatus(contractStatus);

        // 替换非系统字段
        empPaperContractDO.setCompanyId(empPaperContractUpdateDTO.getCompanyId());
        empPaperContractDO.setEmpId(empPaperContractUpdateDTO.getEmpId());
        empPaperContractDO.setNumber(empPaperContractUpdateDTO.getNumber());
        empPaperContractDO.setType(empPaperContractUpdateDTO.getType());
        empPaperContractDO.setName(empPaperContractUpdateDTO.getName());
        empPaperContractDO.setTimeLimit(empPaperContractUpdateDTO.getTimeLimit());
        empPaperContractDO.setTimeLimitType(empPaperContractUpdateDTO.getTimeLimitType());
        empPaperContractDO.setStartTime(empPaperContractUpdateDTO.getStartTime());
        empPaperContractDO.setEndTime(empPaperContractUpdateDTO.getEndTime());
        empPaperContractDO.setCompanyName(empPaperContractUpdateDTO.getCompanyName());
        empPaperContractDO.setStatus(empPaperContractUpdateDTO.getStatus());
        empPaperContractDO.setSubscribeTime(empPaperContractUpdateDTO.getSubscribeTime());
        empPaperContractDO.setRemarks(empPaperContractUpdateDTO.getRemarks());
        empPaperContractDO.setFile(empPaperContractUpdateDTO.getFile());


        //合同到期时间修改发送合同到期通知
        List<EmpPaperContractDO> empPaperContractDOList = new ArrayList<>();
        empPaperContractDOList.add(empPaperContractDO);
        sendContractNotice(empPaperContractDOList);

        //根据主键更新，更新null值
        return updateById(empPaperContractDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    /**
     * 合同信息修改后，发送到期通知
     *
     * @param empPaperContractDOList 纸质合同
     */
    private void sendContractNotice(List<EmpPaperContractDO> empPaperContractDOList) {
        try {
            NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                    NoticeConstants.RETIRE, empPaperContractDOList.get(0).getCompanyId());
            if (ruleSettingVO == null || ruleSettingVO.getId() == null || !ruleSettingVO.getEnableStatus()) {
                return;
            }
            Iterator<EmpPaperContractDO> iterator = empPaperContractDOList.iterator();
            while (iterator.hasNext()) {
                EmpPaperContractDO next = iterator.next();
                if (next.getEndTime() == null) {
                    iterator.remove();
                    continue;
                }
                EmpPaperContractDO empPaperContractDO = selectDOById(next.getId());
                if (empPaperContractDO.getEndTime() != null && DateUtil.isSameTime(empPaperContractDO.getEndTime(), next.getEndTime())) {
                    iterator.remove();
                }
            }
            if (CollectionUtils.isEmpty(empPaperContractDOList)) {
                return;
            }
            List<TaskAddDTO> taskAddDTOList = sendNoticeTask.addEmpPaperContract(empPaperContractDOList, new Date());
            TokenUser tokenUser = new TokenUser();
            tokenUser.setUserId("system");
            tokenUser.setSiteId(HrConstants.DEFAULT);
            taskKit.addTaskList(taskAddDTOList, tokenUser);
        } catch (Exception e) {
            log.info("合同信息修改后，发送到期通知处理失败");
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empPaperContractIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empPaperContractIds);
    }


    @Override
    public EmpPaperContractVO selectById(String empPaperContractId, String siteId) {
        EmpPaperContractDO empPaperContractDO = selectDOById(empPaperContractId, siteId);
        if (empPaperContractDO == null) {
            return null;
        }
        return empPaperContractDO.to(EmpPaperContractVO.class);
    }

    @Override
    public EmpPaperContractDO selectDOById(String empPaperContractId) {
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("id", empPaperContractId);
        return empPaperContractDAO.selectOneByExample(example);
    }

    @Override
    public List<EmpPaperContractListVO> select(EmpPaperContractQuery empPaperContractQuery, String siteId) {
        List<EmpPaperContractDO> empPaperContractDOList = selectDO(empPaperContractQuery, siteId);
        if (CollectionUtils.isEmpty(empPaperContractDOList)) {
            return empPaperContractDOList == null ? null : new ArrayList<>();
        }
        return empPaperContractDOList.stream()
                .map(empPaperContractDO -> empPaperContractDO.to(EmpPaperContractListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpPaperContractQuery empPaperContractQuery, String siteId) {
        Example example = buildExample(empPaperContractQuery, siteId);
        return empPaperContractDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpPaperContractListVO> selectPage(EmpPaperContractQuery empPaperContractQuery, String siteId) {
        Example example = buildExample(empPaperContractQuery, siteId);
        Page<EmpPaperContractDO> page = empPaperContractDAO.selectPageByExample(example,
                empPaperContractQuery.getPageNo(),
                empPaperContractQuery.getPageSize());

        return page.to(EmpPaperContractListVO.class);
    }

    @Override
    public Page<EmpPaperContractListVO> selectPageByEmpInfo(EmpPaperContractQuery empPaperContractQuery, TokenUser tokenUser) {
        Example example = buildExample(empPaperContractQuery, tokenUser.getSiteId());
        // 构造查询条件
        if (StrKit.isNotEmpty(empPaperContractQuery.getEmpStatus())) {
            // 员工状态
            List<EmpInfoDO> empInfoDOList = empInfoService.selectByCompanyIdAndStatus(
                    empPaperContractQuery.getCompanyIdList(), empPaperContractQuery.getEmpStatus(), tokenUser.getSiteId());
            if (CollectionUtils.isEmpty(empInfoDOList)) {
                return new Page<>(empPaperContractQuery.getPageSize(), empPaperContractQuery.getPageNo());
            }
            List<String> empIdList = empInfoDOList.stream().map(EmpInfoDO::getId).collect(Collectors.toList());
            example.and()
                    .andIn("empId", empIdList);
        }
        String nameOrConNameOrPhone = empPaperContractQuery.getUserNameOrConNameOrPhone();
        String idCard = empPaperContractQuery.getIdCard();
        if (StrKit.isNotEmpty(nameOrConNameOrPhone) || StrKit.isNotEmpty(idCard)) {
            // 合同名称/员工名称/手机号
            List<EmpInfoDO> empInfoDOList = empInfoService.selectByNameOrPhoneAndCompanyIdAndIdCard(
                    nameOrConNameOrPhone, empPaperContractQuery.getCompanyIdList(), idCard, tokenUser);
            List<String> empIdList = empInfoDOList.stream().map(EmpInfoDO::getId).collect(Collectors.toList());
            if (StrKit.isEmpty(nameOrConNameOrPhone)) {
                if (CollectionKit.isEmpty(empIdList)) {
                    return new Page<>(empPaperContractQuery.getPageSize(), empPaperContractQuery.getPageNo());
                }
                example.and()
                        .andIn("empId", empIdList);
            } else {
                if (CollectionKit.isEmpty(empIdList)) {
                    example.and()
                            .orLike("name", "%" + empPaperContractQuery.getUserNameOrConNameOrPhone() + "%");
                } else {
                    example.and()
                            .orLike("name", "%" + empPaperContractQuery.getUserNameOrConNameOrPhone() + "%")
                            .orIn("empId", empIdList);
                }
            }
        }
        Page<EmpPaperContractDO> page = empPaperContractDAO.selectPageByExample(example,
                empPaperContractQuery.getPageNo(),
                empPaperContractQuery.getPageSize());
        Page<EmpPaperContractListVO> pageVO = page.to(EmpPaperContractListVO.class);
        // 构造前端返回值
        List<EmpPaperContractListVO> empPaperContractListVOList = pageVO.getEntities();
        if (CollectionUtils.isEmpty(empPaperContractListVOList)) {
            return new Page<>(empPaperContractQuery.getPageSize(), empPaperContractQuery.getPageNo());
        }
        this.setOtherInfo(empPaperContractListVOList, tokenUser);

        return pageVO;
    }

    /**
     * 设置纸质合同前端需要展示的值
     *
     * @param empPaperContractListVOList
     * @param tokenUser
     */
    private void setOtherInfo(List<EmpPaperContractListVO> empPaperContractListVOList, TokenUser tokenUser) {
        // 用工单位Ids
        List<String> companyIds = empPaperContractListVOList
                .parallelStream().map(EmpPaperContractListVO::getCompanyId).collect(Collectors.toList());
        List<CompanyDO> companyDOList = companyService.selectByIdsNotSiteId(companyIds);
        // 用工单位Id-name
        Map<String, String> companyIdNameMap = companyDOList.parallelStream()
                .collect(Collectors.toMap(BaseDO::getId, CompanyDO::getName));
        empPaperContractListVOList.forEach(empPaperContractListVO -> {
            EmpInfoDO empInfoDO = empInfoService.selectDOByIdIgnoreValid(empPaperContractListVO.getEmpId());
            if (empInfoDO == null) {
                empPaperContractListVO.setEmpName("员工被删除");
                empPaperContractListVO.setEmpIdCard("员工被删除");
                empPaperContractListVO.setPhone("员工被删除");
            } else {
                empPaperContractListVO.setEmpIdCard(empInfoDO.getIdCard());
                empPaperContractListVO.setEmpName(empInfoDO.getName());
                empPaperContractListVO.setPhone(empInfoDO.getPhone());
            }
            if (empPaperContractListVO.getEndTime() != null) {
                // 剩余有效时间
                long daysBetween = DateKit8.getDaysBetween(new Date(), empPaperContractListVO.getEndTime());
                if (empPaperContractListVO.getEndTime().compareTo(new Date()) < 0) {
                    daysBetween *= -1;
                }
                empPaperContractListVO.setRemainingValidTime(daysBetween);
            }
            if (empPaperContractListVO.getTimeLimit() != null && empPaperContractListVO.getTimeLimitType() != null) {
                // 合同期限
                String contractLine = empPaperContractListVO.getTimeLimit()
                        + ContractDateEnum.find(empPaperContractListVO.getTimeLimitType()).getDesc();
                empPaperContractListVO.setContractLine(contractLine);
            }
            // 放入用工单位名称
            empPaperContractListVO.setCompanyName(companyIdNameMap.get(empPaperContractListVO.getCompanyId()));
        });
    }

    @Override
    public EmpPaperContractDO selectDOById(String empPaperContractId, String siteId) {
        return listById(empPaperContractId, siteId);
    }

    @Override
    public List<EmpPaperContractDO> selectDO(EmpPaperContractQuery empPaperContractQuery, String siteId) {
        Example example = buildExample(empPaperContractQuery, siteId);
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void publishEmpPaperContractList(List<EmpPaperContractDTO> empPaperContractList, String companyId, String empId, TokenUser tokenUser) {
        // 删除某员工所有的
        deleteByEmpId(empId, tokenUser);

        if (CollectionUtils.isEmpty(empPaperContractList)) {
            return;
        }

        empPaperContractList.forEach(empPaperContractDTO -> {
            empPaperContractDTO.setCompanyId(companyId);
            empPaperContractDTO.setEmpId(empId);
            //新增
            EmpPaperContractAddDTO empPaperContractAddDTO = empPaperContractDTO.to(EmpPaperContractAddDTO.class);
            save(empPaperContractAddDTO, tokenUser);
        });
    }

    @Override
    public List<EmpPaperContractDO> listContractByEmpId(String empId, String siteId) {
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("empId", empId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpPaperContractDO> listContractByEmpIdList(String companyId, List<String> empIdList,
                                                            TokenUser tokenUser) {
        if (StrKit.isEmpty(companyId) || CollectionUtils.isEmpty(empIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andIn("empId", empIdList);
        example.orderBy("gmtCreate").desc();
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpPaperContractDO> listContractByEmpIdList(List<String> empIdList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("empId", empIdList);
        example.orderBy("gmtCreate").desc();
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpPaperContractDO> listAllNoExpireContract() {
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andIsNotNull("companyId")
                .andEqualTo("valid", true)
                .andIsNotNull("endTime")
                .andGreaterThan("endTime", DateKit8.getCurrentDay(DateKit8.DATE));
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpPaperContractExcelVO importFile(File file, TokenUser tokenUser, String companyId) {

        // 纸质合同
        EmpPaperContractListener empPaperContractListener = new EmpPaperContractListener();
        empPaperContractListener.setCompanyId(companyId);
        empPaperContractListener.setForce(true);
        empPaperContractListener.setTokenUser(tokenUser);
        // 读取excel 并且入库
        EasyExcel.read(file, EmpPaperContractImportDTO.class, empPaperContractListener).sheet("纸质合同").headRowNumber(2).doRead();

        EmpPaperContractExcelVO empPaperContractExcelVO = empPaperContractListener.getEmpPaperContractExcelVO();
        ParamException.notNull(empPaperContractExcelVO, "导入失败，请检查导入模板及Sheet标签名称");
        if (!CollectionUtils.isEmpty(empPaperContractExcelVO.getImportFailList())) {
            String excelFilePath = exportFailData(empPaperContractExcelVO.getImportFailList());
            empPaperContractExcelVO.setExcelFilePath(excelFilePath);
        }
        return empPaperContractExcelVO;
    }

    @Override
    public HrPaperContractCountVO statisticsCountByCompanyId(String companyId, TokenUser tokenUser) {
        if (StrKit.isEmpty(companyId)) {
            throw new ParamException("用工单位id必传！");
        }
        HrPaperContractCountVO hrPaperContractCountVO = new HrPaperContractCountVO();
        Example example = new Example(EmpPaperContractDO.class);
        // 全部合同数量
        example.clear();
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer allCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setAllCount(allCount);
        // 未执行合同数量
        example.clear();
        example.and()
                .andEqualTo("status", ContractStatusEnum.NOT_STARTED.getValue())
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer noExecuteCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setNoExecuteCount(noExecuteCount);
        // 执行中合同数量
        example.clear();
        example.and()
                .andEqualTo("status", ContractStatusEnum.IMPLEMENT.getValue())
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer executeCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setExecuteCount(executeCount);
        // 已到期合同数量
        example.clear();
        example.and()
                .andEqualTo("status", ContractStatusEnum.EXPIRE.getValue())
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer expireCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setExpireCount(expireCount);
        // 其他合同数量
        example.clear();
        example.and()
                .andIsNull("status")
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer otherCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setOtherCount(otherCount);
        // 即将到期合同数量
        example.clear();
        example.and()
                .andCondition("DATEDIFF(end_time,now()) <= 90")
                .andCondition("DATEDIFF(end_time,now()) >= 0")
                .andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        Integer willExpireCount = empPaperContractDAO.selectCountByExample(example);
        hrPaperContractCountVO.setWillExpireCount(willExpireCount);
        return hrPaperContractCountVO;
    }

    @Override
    public List<EmpPaperContractDO> selectAll() {
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("valid", true);
        return empPaperContractDAO.selectByExample(example);
    }

    @Override
    public String exportPaperContract(EmpPaperContractQuery empPaperContractQuery, TokenUser tokenUser) {

        ParamException.notEmpty(empPaperContractQuery.getExportColumns(), "没有需要导出的表头，请调整检索条件");
        Example example = new Example(EmpPaperContractDO.class);
        if (CollectionUtils.isEmpty(empPaperContractQuery.getIdList())) {
            // 没有指定,根据条件查询下载
            example = buildExample(empPaperContractQuery, tokenUser.getSiteId());
            // 构造查询条件
            if (StrKit.isNotEmpty(empPaperContractQuery.getEmpStatus())) {
                // 员工状态
                List<EmpInfoDO> empInfoDOList = empInfoService.selectByCompanyIdAndStatus(
                        empPaperContractQuery.getCompanyIdList(), empPaperContractQuery.getEmpStatus(), tokenUser.getSiteId());
                if (CollectionUtils.isEmpty(empInfoDOList)) {
                    throw new ParamException("没有需要导出的数据，请调整检索条件");
                }
                List<String> empIdList = empInfoDOList.stream().map(EmpInfoDO::getId).collect(Collectors.toList());
                example.and()
                        .andIn("empId", empIdList);
            }
            String nameOrConNameOrPhone = empPaperContractQuery.getUserNameOrConNameOrPhone();
            String idCard = empPaperContractQuery.getIdCard();
            if (StrKit.isNotEmpty(nameOrConNameOrPhone) || StrKit.isNotEmpty(idCard)) {
                // 合同名称/员工名称/手机号
                List<EmpInfoDO> empInfoDOList = empInfoService.selectByNameOrPhoneAndCompanyIdAndIdCard(
                        nameOrConNameOrPhone, empPaperContractQuery.getCompanyIdList(), idCard, tokenUser);
                List<String> empIdList = empInfoDOList.stream().map(EmpInfoDO::getId).collect(Collectors.toList());
                if (StrKit.isEmpty(nameOrConNameOrPhone)) {
                    if (CollectionKit.isEmpty(empIdList)) {
                        throw new ParamException("没有需要导出的数据，请调整检索条件");
                    }
                    example.and()
                            .andIn("empId", empIdList);
                } else {
                    if (CollectionKit.isEmpty(empIdList)) {
                        example.and()
                                .orLike("name", "%" + empPaperContractQuery.getUserNameOrConNameOrPhone() + "%");
                    } else {
                        example.and()
                                .orLike("name", "%" + empPaperContractQuery.getUserNameOrConNameOrPhone() + "%")
                                .orIn("empId", empIdList);
                    }
                }
            }
        } else {
            // 根据id查询
            example.and().andIn("id", empPaperContractQuery.getIdList());
        }
        List<EmpPaperContractDO> empPaperContractDOList = empPaperContractDAO.selectByExample(example);

        ParamException.notEmpty(empPaperContractDOList, "没有需要导出的数据，请调整检索条件");
        List<EmpPaperContractListVO> empPaperContractListVOList = empPaperContractDOList.stream()
                .map(empPaperContractDO -> empPaperContractDO.to(EmpPaperContractListVO.class))
                .collect(Collectors.toList());
        this.setOtherInfo(empPaperContractListVOList, tokenUser);
        // 表头为中文名，所以需要再定义一个英文名的集合，准备反射获取属性
        List<List<String>> headList = new ArrayList<>();
        // 表头英文名集合
        List<String> headPropertyList = new ArrayList<>();
        // 定义所有的数据集合
        List<List<String>> dataList = new ArrayList<>();
        for (EmpInfoExportColumn empInfoExportColumn : empPaperContractQuery.getExportColumns()) {
            // 定义每一个表头
            List<String> oneHead = new ArrayList<>();
            oneHead.add(empInfoExportColumn.getTitle());
            headList.add(oneHead);
            headPropertyList.add(empInfoExportColumn.getDataIndex());
        }
        for (EmpPaperContractListVO empPaperContractListVO : empPaperContractListVOList) {
            // 定义每一条数据
            List<String> oneData = new ArrayList<>();
            //循环表头,往每一条数据中，拼装数据
            for (String head : headPropertyList) {
                Field field;
                try {
                    field = empPaperContractListVO.getClass().getDeclaredField(head);
                } catch (NoSuchFieldException e) {
                    log.error("表头传入错误：heard：{}", head);
                    throw new ParamException("表头传入错误");
                }
                field.setAccessible(true);
                try {
                    if (field.get(empPaperContractListVO) != null) {
                        if ("class java.util.Date".equals(field.getGenericType().toString())) {
                            // 日期类型
                            Date date = (Date) field.get(empPaperContractListVO);
                            oneData.add(DateKit8.format2Date(date));
                        } else {
                            String value = ContractFieldToString.fieldToStringEmpPaperContract(field, empPaperContractListVO);
                            oneData.add(value);
                        }
                    } else {
                        oneData.add("");
                    }
                } catch (IllegalAccessException e) {
                    log.error("表头传入错误：heard：{}", head);
                    throw new ParamException("表头传入错误");
                }
            }
            dataList.add(oneData);
        }
        return ExcelKit.exportExcelDynamic(empPaperContractQuery.getEnName(), "合同导出", dataList, headList);
    }

    /**
     * 导出错误数据
     */
    private String exportFailData(List<EmpPaperContractImportDTO> importFailList) {
        // 导出excel
        String excelFilePath = ExcelKit.exportExcel("empPaperContract", "电子合同",
                EmpPaperContractImportDTO.class, importFailList);
        String cleanPath = org.springframework.util.StringUtils.cleanPath(excelFilePath);
        File file = new File(excelFilePath);
        log.info("本地路径：" + file.getPath());

        FileItem fileItem = createFileItem(file);
        CommonsMultipartFile[] commonsMultipartFiles = new CommonsMultipartFile[1];
        commonsMultipartFiles[0] = new CommonsMultipartFile(fileItem);
        String fileName = "纸质合同导入错误数据-" + DateUtil.format(new Date(), "yyyy.MM.dd");
        TokenUser tokenUser = UserContext.getUser();

        IFileProviderService fileProviderService = BeanKit.getBean(IFileProviderService.class);
        List<String> list =
                fileProviderService.uploadAndSetName(commonsMultipartFiles, "inline", fileName, tokenUser);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * File 转 FileItem
     */
    private FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

    @Override
    public Integer getStatus(Date startTime, Date endTime) {
        if (startTime != null && endTime != null) {
            // 开始时间为当天第一秒
            startTime = DateKit8.getStartTime(startTime);
            // 结束时间为当天最后一秒
            endTime = DateKit8.getEndTime(endTime);
            long newDate = System.currentTimeMillis();
            if (newDate < startTime.getTime()) {
                // 开始时间大于现在 未执行
                return ContractStatusEnum.NOT_STARTED.getValue();
            } else if (newDate > endTime.getTime()) {
                // 结束时间小于现在 已到期
                return ContractStatusEnum.EXPIRE.getValue();
            }
            // 执行中
            return ContractStatusEnum.IMPLEMENT.getValue();
        }
        return null;
    }

    /**
     * 根据查询参数，构建example
     *
     * @param empPaperContractQuery 查询参数
     * @param siteId                所属站点id
     * @return example
     */
    private Example buildExample(EmpPaperContractQuery empPaperContractQuery, String siteId) {
        Example example = new Example(EmpPaperContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empPaperContractQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empPaperContractQuery.getCompanyId());
        }
        if (empPaperContractQuery.getEmpId() != null) {
            example.and().andEqualTo("empId", empPaperContractQuery.getEmpId());
        }
        if (empPaperContractQuery.getNumber() != null) {
            example.and().andEqualTo("number", empPaperContractQuery.getNumber());
        }
        if (empPaperContractQuery.getType() != null) {
            example.and().andEqualTo("type", empPaperContractQuery.getType());
        }
        if (empPaperContractQuery.getName() != null) {
            example.and().andLike("name", "%" + empPaperContractQuery.getName() + "%");
        }
        if (empPaperContractQuery.getTimeLimit() != null) {
            example.and().andEqualTo("timeLimit", empPaperContractQuery.getTimeLimit());
        }
        if (empPaperContractQuery.getTimeLimitType() != null) {
            example.and().andEqualTo("timeLimitType", empPaperContractQuery.getTimeLimitType());
        }
        if (empPaperContractQuery.getStartTimeStart() != null &&
                empPaperContractQuery.getStartTimeEnd() != null) {
            example.and().andBetween("startTime", empPaperContractQuery.getStartTimeStart(),
                    empPaperContractQuery.getStartTimeEnd());
        }
        if (empPaperContractQuery.getEndTimeStart() != null &&
                empPaperContractQuery.getEndTimeEnd() != null) {
            example.and().andBetween("endTime", empPaperContractQuery.getEndTimeStart(),
                    empPaperContractQuery.getEndTimeEnd());
        }
        if (empPaperContractQuery.getCompanyName() != null) {
            example.and().andEqualTo("companyName", empPaperContractQuery.getCompanyName());
        }
        if (empPaperContractQuery.getStatus() != null) {
            if (empPaperContractQuery.getStatus() == -1) {
                example.and().andIsNull("status");
            } else {
                example.and().andEqualTo("status", empPaperContractQuery.getStatus());
            }
        }
        if (empPaperContractQuery.getSubscribeTimeStart() != null &&
                empPaperContractQuery.getSubscribeTimeEnd() != null) {
            example.and().andBetween("subscribeTime", empPaperContractQuery.getSubscribeTimeStart(),
                    empPaperContractQuery.getSubscribeTimeEnd());
        }
        if (empPaperContractQuery.getRemarks() != null) {
            example.and().andEqualTo("remarks", empPaperContractQuery.getRemarks());
        }
        if (empPaperContractQuery.getFile() != null) {
            example.and().andEqualTo("file", empPaperContractQuery.getFile());
        }
        if (empPaperContractQuery.getWillExpire() != null && empPaperContractQuery.getWillExpire()) {
            example.and()
                    .andCondition("DATEDIFF(end_time,now()) <= 90")
                    .andCondition("DATEDIFF(end_time,now()) >= 0");
        }
        if (!CollectionUtils.isEmpty(empPaperContractQuery.getCompanyIdList())) {
            example.and()
                    .andIn("companyId", empPaperContractQuery.getCompanyIdList());
        }
        // 排序
        ExampleKit.setExampleOrder(example, empPaperContractQuery.getOrders());
        return example;
    }

    /**
     * 删除某个员工所有的
     *
     * @param empId     员工id
     * @param tokenUser 当前用户
     */
    private void deleteByEmpId(String empId, TokenUser tokenUser) {
        // 逻辑删除
        List<EmpPaperContractDO> list = listContractByEmpId(empId, tokenUser.getSiteId());
        String[] ids = list.stream()
                .map(BaseDO::getId).toArray(String[]::new);
        deleteByIds(tokenUser, ids);
    }
}




